package momo.multitree.visual;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Set;

import momo.multitree.structure.Edge;
import momo.multitree.structure.Graph;
import momo.multitree.structure.Node;

public class PajekGraphOutput implements GraphVisualOutput
{
	private Graph g;
	private HashMap<String, Integer> nodeMap;
	
	public PajekGraphOutput()
	{
		nodeMap = new HashMap<String, Integer>();
	}
	
	public void setGraph(Graph g)
	{
		this.g = g;
	}

	public void output(String filenameWOExt) throws Exception
	{
		if (g == null)
			throw new RuntimeException("Graph is null");
		
		StringBuffer buffer = new StringBuffer();
		outputNode(buffer);
		outputEdge(buffer);
		outputToFile("visual/Pajek/input/"+filenameWOExt+".net", buffer.toString());
		outputMacroFile(filenameWOExt);
	}
	
	private void outputNode(StringBuffer buffer)
	{
		Set<Node> nodes = g.getNodes();
		int nodeSize = nodes.size();
		buffer.append("*Vertices "+nodeSize+"\r");

		int index = 1;
		for(Node n: nodes)
		{
			double workload = rdTo(n.getWorkloadRate(), 2);
			double stability = rdTo(n.getStability(), 2);
			buffer.append(index + " \"" + n.getId()+"\\n["
					+workload+", "+stability
					+"]\" 1 1 x_fact 7 y_fact 7\r");
			nodeMap.put(n.getId(), index);
			index ++;
		}
	}
	
	private void outputEdge(StringBuffer buffer)
	{
		buffer.append("*Edges\r");
		Set<Edge> edges = g.getEdges();
		for(Edge e: edges)
		{
			Node h = e.getHeadNode();
			Node t = e.getTailNode();
			double latency = rdTo(e.getLatency(h), 2);
			double cost = rdTo(e.getCost(h), 2);
			buffer.append(nodeMap.get(h.getId()) + " " + nodeMap.get(t.getId()) 
					+ " 1 l \"("+latency+", "+cost+")\"\r");
		}
	}
	
	private void outputToFile(String filename, String data) throws Exception
	{
		PrintWriter out = new PrintWriter(filename);
		out.println(data);
		out.flush();
		out.close();
	}
	
	private void outputMacroFile(String filename) throws Exception
	{
		StringBuffer buffer = new StringBuffer();
		File iniFile = new File("visual/Pajek/ini/pajek_config.ini");
		File inputFile = new File("visual/Pajek/input/"+filename+".net");
		File outputFile = new File("visual/Pajek/output/"+filename+".svg");
		
		buffer.append("NETBEGIN 1\r");
		buffer.append("CLUBEGIN 1\r");
		buffer.append("PERBEGIN 1\r");
		buffer.append("CLSBEGIN 1\r");
		buffer.append("HIEBEGIN 1\r");
		buffer.append("VECBEGIN 1\r");
		buffer.append("LOADINI \"" + iniFile.getAbsolutePath()+"\"\r");
		buffer.append("N 1 RDN \"" + inputFile.getAbsolutePath()+"\"\r");
		buffer.append("E 1 DRAW 0 0 0 0 0\r");
		buffer.append("E 1 KAMADA\r");
		buffer.append("E 1 SVG 0 0 0 0 0 \"" + outputFile.getAbsolutePath() + "\" 2 0\r" );
		outputToFile("visual/Pajek/macro/"+filename+".mcr", buffer.toString());
	}
	
	private double rdTo(double value, int decimalPlace)
	{
		double times = Math.pow(10, decimalPlace);
		double newVal = Math.round(value * times)/times;
		return newVal;
	}
}
